﻿using System;

namespace Dicide.ViewModels
{
    public class ComponentViewModel : BindableBase
    {
        public virtual void OnInputsChanged()
        {
            _leftInput = HasLeftConnector && _left != null && _left.RightOutput;
            _topInput = HasTopConnector && _top != null && _top.BottomOutput;
            _rightInput = HasRightConnector && _right != null && _right.LeftOutput;
            _bottomInput = HasBottomConnector && _bottom != null && _bottom.TopOutput;
        }

        public virtual void UpdateHasConnectors()
        {
        }

        public virtual void UpdateOutputs()
        {
        }

        public void OnTapped()
        {
            Rotation += 90;
            if (Rotation >= 360)
            {
                Rotation = 0;
            }

            UpdateHasConnectors();
            OnInputsChanged();
            UpdateOutputs();
        }

        Boolean _on;
        public Boolean On
        {
            get { return _on; }
            set
            {
                SetProperty<Boolean>(ref _on, value);
                UpdateOutputs();
            }
        }

        Boolean _leftOutput;
        public Boolean LeftOutput
        {
            get { return _leftOutput; }
            set { SetProperty<Boolean>(ref _leftOutput, value); }
        }

        Boolean _topOutput;
        public Boolean TopOutput
        {
            get { return _topOutput; }
            set { SetProperty<Boolean>(ref _topOutput, value); }
        }

        Boolean _rightOutput;
        public Boolean RightOutput
        {
            get { return _rightOutput; }
            set { SetProperty<Boolean>(ref _rightOutput, value); }
        }

        Boolean _bottomOutput;
        public Boolean BottomOutput
        {
            get { return _bottomOutput; }
            set { SetProperty<Boolean>(ref _bottomOutput, value); }
        }

        Boolean _hasLeftConnector;
        public Boolean HasLeftConnector
        {
            get { return _hasLeftConnector; }
            set { SetProperty<Boolean>(ref _hasLeftConnector, value); }
        }

        Boolean _hasTopConnector;
        public Boolean HasTopConnector
        {
            get { return _hasTopConnector; }
            set { SetProperty<Boolean>(ref _hasTopConnector, value); }
        }

        Boolean _hasRightConnector;
        public Boolean HasRightConnector
        {
            get { return _hasRightConnector; }
            set { SetProperty<Boolean>(ref _hasRightConnector, value); }
        }

        Boolean _hasBottomConnector;
        public Boolean HasBottomConnector
        {
            get { return _hasBottomConnector; }
            set { SetProperty<Boolean>(ref _hasBottomConnector, value); }
        }

        int _rotation;
        public int Rotation
        {
            get { return _rotation; }
            set { SetProperty<int>(ref _rotation, value); }
        }

        ComponentViewModel _left;
        public ComponentViewModel Left
        {
            get { return _left; }
            set
            {
                _leftInput = false;
                if (_left != null)
                {
                    _left.PropertyChanged -= LeftPropertyChanged;
                }
                SetProperty<ComponentViewModel>(ref _left, value);
                if (_left != null)
                {
                    _left.PropertyChanged += LeftPropertyChanged;
                    _leftInput = _left.RightOutput;
                }
                OnInputsChanged();
            }
        }

        ComponentViewModel _top;
        public ComponentViewModel Top
        {
            get { return _top; }
            set
            {
                _topInput = false;
                if (_top != null)
                {
                    _top.PropertyChanged -= TopPropertyChanged;
                }
                SetProperty<ComponentViewModel>(ref _top, value);
                if (_top != null)
                {
                    _top.PropertyChanged += TopPropertyChanged;
                    _topInput = _top.BottomOutput;
                }
                OnInputsChanged();
            }
        }

        ComponentViewModel _right;
        public ComponentViewModel Right
        {
            get { return _right; }
            set
            {
                _rightInput = false;
                if (_right != null)
                {
                    _right.PropertyChanged -= RightPropertyChanged;
                }
                SetProperty<ComponentViewModel>(ref _right, value);
                if (_right != null)
                {
                    _right.PropertyChanged += RightPropertyChanged;
                    _rightInput = _right.LeftOutput;
                }
                OnInputsChanged();
            }
        }

        ComponentViewModel _bottom;
        public ComponentViewModel Bottom
        {
            get { return _bottom; }
            set
            {
                _bottomInput = false;
                if (_bottom != null)
                {
                    _bottom.PropertyChanged -= BottomPropertyChanged;
                }
                SetProperty<ComponentViewModel>(ref _bottom, value);
                if (_bottom != null)
                {
                    _bottom.PropertyChanged += BottomPropertyChanged;
                    _bottomInput = _bottom.TopOutput;
                }
                OnInputsChanged();
            }
        }

        protected Boolean _leftInput;
        protected Boolean _topInput;
        protected Boolean _rightInput;
        protected Boolean _bottomInput;

        void LeftPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            OnInputsChanged();
        }

        void TopPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            OnInputsChanged();
        }

        void RightPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            OnInputsChanged();
        }

        void BottomPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            OnInputsChanged();
        }
    }
}
